package nusar

import groovy.sql.Sql

class AlumnoController {

	def beforeInterceptor = [action:this.&autenticar]
	static defaultAction = "principal"
	def mensajePendiente

	
	def autenticar(){
	
		// Si la sesion no se ha creado
		if(!session.user || !session.user.alumno)
		{
			// Se regresa a la pantalla de login
			redirect(controller: "usuario", action:"login")
		}
	}
	
	
	// Boton Salir, Vista Principal
	def logout(){
		
		// Se invalida la sesion
		session.user = null
		
		// Se regresa a la pantalla de login
		redirect(controller: "usuario", action:"login")
	}
	
	
	def principal(){
		
		
		// No intentar obtener informacion si la sesion no esta creada
		if(!session.user || !session.user.alumno)
			return
			
		// Informaion general del alumno
		def infoAlumno = session.user.infoAlumno
		
		// Obtener las materias que cursa el alumno con sus horarios (Carga academica)
		def horarioAlumno = session.user.materias
		
		// Obtenemos la solicitud del alumno
		def solicitudes = Solicitud.findAllByAlumno(Alumno.get(session.user.infoAlumno.matricula))
		
		// Estatus del alumno
		def estatus = Alumno.get(session.user.infoAlumno.matricula).estatus
		
		// Si la solicitud ya se creo y esta en estado de Borrador, valor = display:none
		// En caso contrario, valor = ""
		String estadoBtnQuitar	
		
		if(solicitudes)
		{
			for(Solicitud solicitud : solicitudes)
			{	
				if(solicitud.peticiones.isEmpty() || solicitud.estado.equalsIgnoreCase("Pendiente") || solicitud.estado.equalsIgnoreCase("Revisada"))
				{
					mensajePendiente="display:none";
					estadoBtnQuitar="display:none";
				}
				else
				{
					mensajePendiente="";
					estadoBtnQuitar="";
				}
			}
		}
		else
		{
			mensajePendiente="display:none";
			estadoBtnQuitar="display:none";
		}
		
		[infoAlumno: infoAlumno,
		 horarioAlumno: horarioAlumno,
		 solicitudes: solicitudes,
		 estadoBtnQuitar: estadoBtnQuitar,
		 mensajePendiente: mensajePendiente,
		 estatus: estatus]						
		
	}
	
	
	def crearSolicitud(){
		
		// No intentar obtener informacion si la sesion no esta creada
		if(!session.user || !session.user.alumno)
			return
			
		// Informacion sobre todas las materias disponibles y sus horarios (no cursadas por alumno)
		def materias_horario = UABCService.getAllMaterias()
		session.user.allMaterias = materias_horario
		
		// Obtener las materias que cursa el alumno con sus horarios (Carga academica)
		HashMap horarioAlumno = session.user.materias
		
		// Nombre del alumno
		def nombre = session.user.infoAlumno.nombre
		
		// Variable que definira el estilo del boton "Crear Solicitud"
		def mostrarBoton = ""
		
		def alumno = Alumno.get(session.user.infoAlumno.matricula)
		
		// Buscamos si el alumno tiene una solicitud en estado Pendiente
		def solicitudP = Solicitud.findByAlumnoAndEstado(Alumno.get(session.user.infoAlumno.matricula), "Pendiente")
		
		// El alumno no puede mandar mas de dos solicitudes
		if(alumno.solicitudesEnviadas < 2 || solicitudP)
		{
			if(materias_horario)
			{
				// Quitar las materias que esta cursando el alumno
				for (Object key : horarioAlumno.keySet())
				{
					materias_horario.remove(key)
				}
				
				// Quitar las materias que ya curso el alumno
				for(Object key: session.user.cardex.keySet())
				{
					materias_horario.remove(key)
				}
			}
			
			
			// Obtenemos las solicitudes del alumno(maximo deben ser 2)
			def solicitudes = Solicitud.findAllByAlumno(alumno)
			
			if( solicitudes)
			{
				for(Solicitud solicitud : solicitudes)
				{
					// Si ya tenemos materias en la solicitud, esas tampoco se deben de mostrar
					if(solicitud.peticiones.size() > 0)
					{
						for(Solicitud_Materias peticion : solicitud.peticiones)
						{
							// Checamos si quitar materias del horario del alumno
							if(peticion.tipo.equalsIgnoreCase("Baja"))	
							{	
								horarioAlumno.remove(""+peticion.materia.iden)
							}
							else
							{
								materias_horario.remove(""+peticion.materia.iden)
							}
						}
					}
				}
			}	
			
			if(solicitudP)
				flash.message = "<div id=\"error\">Tú solicitud está pendiente, espera a que sea revisada para que puedas crear otra.</div>"
			
			// o si ya no hay materias para dar de alta o baja, valor = display:none
			// En caso contrario, valor = ""
			if((solicitudP)
			|| (horarioAlumno.size() == 0 && materias_horario.size() == 0))
				mostrarBoton = "display:none"
			
		}
		else	
		{
			// Ya no se deben mostrar las materias disponibles
			horarioAlumno = null
			materias_horario = null
			
			// No se debe mostrar el boton "Crear solicitud
			mostrarBoton = "display:none"
			
			// Mostrar mensaje 
			flash.message = "<div id=\"error\">Ya has enviado dos solicitudes. No puedes crear otra solicitud</div>"
		}
		
		
		
		[materias_horario: materias_horario,
		 horarioAlumno: horarioAlumno,
		 mostrarBoton: mostrarBoton,
		 nombre: nombre]

		
		
	}
	
	
	def guardarMaterias(){
		
		// No intentar obtener informacion si la sesion no esta creada
		if(!session.user || !session.user.alumno)
			return
			
		// Parametros: Los ids de las materias se obtienen de crearSolicitud.gsp
		def idMateriasAltas = []
		def idMateriasBajas = []
		
		idMateriasAltas=params.altas_checkbox
		idMateriasBajas=params.bajas_checkbox
		
		boolean paramsOK = true
		
		def alumno = Alumno.get(session.user.infoAlumno.matricula)
		
		def solicitud = Solicitud.findByAlumnoAndEstadoInList(alumno, ["Pendiente", "Borrador"])
		
		// Verificar que el alumno no haya enviado dos solicitudes
		if(alumno.estatus != null && !alumno.estatus.equalsIgnoreCase(""))
		{
			if(alumno.solicitudesEnviadas < 2)
			{
				  // Numero de solicitudes
				  def numSolicitudes = alumno.solicitudes.size()
				  
				  // Si no esta registrada la solicitud en la BD, crear una con estado de "Borrador"
				  if(numSolicitudes == 0 || (numSolicitudes == 1 && !solicitud) )
				  {
					   // Ejemplo de alta de solicitud, EZB
					   solicitud = new Solicitud(estado: "Borrador",
												 alumno: alumno,
												  coordinador: Coordinador.findByNumTrabajador(session.user.infoAlumno.coordinador.id),
												  fechaEnvio:  (new Date()),
												  estatus: alumno.estatus,
												  periodo: "2012-2")
						   
						// Guardamos la solicitud y checamos si hubo errores
						if( !solicitud.save(flush:true) )
						    solicitud.errors.each {
							   println it
						    }
				  }
					  
				// Verificar que no se cuente con una solicitud en estado Pendiente
				// En este caso, ya no se puede modificar la solicitud
				if(!solicitud.estado.equalsIgnoreCase("Pendiente"))
				{
					  // Verificar que haya al menos una materia seleccionada
					  if( (idMateriasAltas && idMateriasAltas.size() > 0) || (idMateriasBajas && idMateriasBajas.size() > 0) )
					  {
											   
						// Verificar que (Materias Cursadas + Altas - Bajas <= 8)
						int materiasActuales = session.user.materias.size() - Solicitud_Materias.countByTipoAndEstado("Baja", "Aceptada")
						int altas = idMateriasAltas==null ? 0 : idMateriasAltas.size()
						int bajas = idMateriasBajas==null ? 0 : idMateriasBajas.size()
						
						if( (materiasActuales+altas-bajas) <= 8)
						{
							// Baja de Materias
							for(def id : idMateriasBajas)
							{
								// Guardar las materias en la tabla Solicitud_Materias con el estado de "Pendiente"
								def peticion = new Solicitud_Materias( solicitud: solicitud,
																		 tipo: "Baja",
																		 estado: "Pendiente",
																		 materia: Materia.get(id))
				
								if( !peticion.save(flush:true) )
									peticion.errors.each {
										println it
									}
							}
							
							// Alta de Materias
							for(def id : idMateriasAltas)
							{
								// Checar que la materia no se traslape con el horario del alumno (PENDIENTE)
								if(!traslapeMaterias(id, idMateriasAltas))
								{
									// Guardar las materias en la tabla Solicitud_Materias con el estado de "Pendiente"
									def peticion = new Solicitud_Materias( solicitud: solicitud,
																		 tipo: "Alta",
																		 estado: "Pendiente",
																		 materia: Materia.get(id))
								  
									// Incrementar la demanda
									Materia.get(id).demanda++
			  
									if( !peticion.save(flush:true) )
									 	peticion.errors.each {
											 println it
										 }
								}
								else
								{
									println	flash.message = "<div id=\"error\"> "+Materia.get(id).nombre+" se traslapa con otra materia.</div>"
									
									redirect(controller: "Alumno", action: "crearSolicitud")
									return
								}
							}
					}
					else
					{
					println	flash.message = "<div id=\"error\">Tu total de materias es mayor a 8, esto no esta permitido.</div>"
						paramsOK = false
					}
									
						  }
						  else
						  {
					println		  flash.message = "<div id=\"error\">No seleccionaste ninguna materia.</div>"
					 paramsOK = false
						  }
				 }
				 else
				 {
			println		 flash.message = "<div id=\"error\">Ya has enviado una solicitud que esta en espera de ser revisada.</div>"
					 paramsOK = false
				 }
			}
			else
			{
			println	flash.message = "<div id=\"error\">Ya no es posible enviar otra solicitud.</div>"
				paramsOK = false
			}
		}
		else
		{
			println	flash.message = "<div id=\"error\">Debes de seleccionar tu estatus antes de mandar una solicitud.</div>"
			paramsOK = false
		}
	
		
		if(!paramsOK)
		{
			redirect(controller: "Alumno", action: "crearSolicitud")
			return
		}

		// Regresar a la pantalla principal
		redirect(action: "principal")
		
	}
	
	def confirmarSolicitud(){			
			
		// No intentar obtener informacion si la sesion no esta creada
		if(!session.user || !session.user.alumno)
			return
			
		def alumno = Alumno.get(session.user.infoAlumno.matricula)	
		
		// Se incrementa el numero de solicitudes enviadas por el alumno (Alumno.solicitudesEnviadas)
		alumno.solicitudesEnviadas++
		if(!alumno.save(flush:true)){
			alumno.errors.each {
				println it
			}
		}
		
		def solicitud=Solicitud.findByAlumnoAndEstado(alumno, "Borrador")
		
		// Se cambia el estado de la solicitud a "Pendiente"
		solicitud.estado="Pendiente"
		if(!solicitud.save(flush:true)){
			solicitud.errors.each {
				println it
			}
		}
			
		redirect(action:"principal")				
	}
	
	
	def eliminarMateriaSolicitud(){
		
		// No intentar obtener informacion si la sesion no esta creada
		if(!session.user || !session.user.alumno)
			return
			
		// Obtenemos la peticion
		def peticion = Solicitud_Materias.get(params.id)
		
		// Si es una solicitud de Alta, decrementamos su demanda
		if(peticion.tipo.equalsIgnoreCase("Alta"))
			peticion.materia.demanda--;
			
		// Eliminamos la peticion
		peticion.delete(flush: true);
		
		def solicitud = Solicitud.findByAlumnoAndEstado(Alumno.get(session.user.infoAlumno.matricula), "Borrador")
		
		// Eliminamos las dependencias
		solicitud.peticiones.remove(peticion)
		
		if(solicitud.peticiones.isEmpty()){
			mensajePendiente="display:none"
		}
		
		def solicitudes = Solicitud.findAllByAlumno(Alumno.get(session.user.infoAlumno.matricula))
		
		render(template: "listS", model : [solicitudes:solicitudes,mensajePendiente:mensajePendiente])
		
	}
	
	def cambiarEstatus(){
		
		// No intentar obtener informacion si la sesion no esta creada
		if(!session.user || !session.user.alumno)
			return
			
		def estatus = params.id
		if(!estatus.equalsIgnoreCase("Selecciona tu estatus"))
		{
			// Guardamos el estatus del alumno
			session.user.infoAlumno.estatus = estatus
			def alumno = Alumno.get(session.user.infoAlumno.matricula)
			alumno.estatus = estatus
			
			// Salvamos en la BD
			if(!alumno.save(flush:true)){
				alumno.errors.each {
					println it
				}
			}
		}
	}
	
	def traslapeMaterias(def id, def idMaterias){

		// Obtener las materias que cursa el alumno con sus horarios (Carga academica)
		HashMap horarioAlumno = session.user.materias
		
		// Materias que queremos dar de alta
		HashMap<String, HashMap> horarioMateriasAltas = new HashMap<String, HashMap>()
		
		// Materia actual a checar
		HashMap altaHorarioActual = session.user.allMaterias.get(id).diashoras
		
		// Obtenemos la informacion de las materias que daremos de alta
		for(def idMateria : idMaterias)
		{
			// La materia actual no debe incluirse en esta lista
			if(id != idMateria)
			{
				horarioMateriasAltas.put(idMateria, session.user.allMaterias.get(idMateria).diashoras)
			}
		}
		
		// Checamos si la materia que daremos de alta se traslapa con el horario del alumno
		if(checarEntreGrupoMaterias(altaHorarioActual, horarioAlumno, true))
			return true
		
		// Checamos que las materias que se van a dar de alta no se traslapen
		if(checarEntreGrupoMaterias(altaHorarioActual, horarioMateriasAltas, false))
			return true
			
		
		return false
	}
	
	def checarEntreGrupoMaterias(def altaHorarioActual, def grupoHorarioActual, boolean horarioAlumno)
	{
		// Checamos que la materia que vayamos a dar de alta no se traslape con el grupo de materias
		for (Object key : grupoHorarioActual.keySet())
		{
			println "Materia: " + Materia.get(key).nombre
			// Si dimos de baja una materia de nuestro horario,
			// ya no debemos verificar si se traslapa con la materia que se dara de alta
			if(horarioAlumno && !Solicitud_Materias.findByMateriaAndEstado(Materia.get(key), "Aceptada"))
			{
				 def materiaHorarioActual = grupoHorarioActual.get(key).diashoras
				
				// Verificamos el horario de las materias por dia
				for(Object dia : materiaHorarioActual.keySet())
				{
					// Si las dos materias tienen horas de clase el mismo dia,
					// debemos verificar si se traslapan o no
					if(!materiaHorarioActual.get(dia).equalsIgnoreCase("") && !altaHorarioActual.get(dia).equalsIgnoreCase(""))
						if(checarEntreDosMaterias(altaHorarioActual, materiaHorarioActual, dia))
							return true
				}
			}
		}
		
		return false
	}
	
	def checarEntreDosMaterias(def altaHorarioActual, def materiaHorarioActual, def dia)
	{
		// Separamos la hora de inicio de la hora final
		List horasAlta = altaHorarioActual.get(dia).tokenize(" - ")
		
		// Obtenemos la hora de inicio y final de la materia que se dara de ALTA
		int inicioMateriaAlta = horasAlta.first().tokenize(":").first().toInteger()
		int finMateriaAlta = horasAlta.last().tokenize(":").first().toInteger()
		
		println "Inicio Alta: " + inicioMateriaAlta
		println "Final Alta: " + finMateriaAlta
		
		List horasMateria = materiaHorarioActual.get(dia).tokenize(" - ")
		
		// Obtenemos la hora de inicio y final de la materia de nuestro HORARIO
		int inicioMateriaHorario = horasMateria.first().tokenize(":").first().toInteger()
		int finMateriaHorario = horasMateria.last().tokenize(":").first().toInteger()
		
		println "Inicio Materia: " + inicioMateriaHorario
		println "Final Materia: " + finMateriaHorario
		
		//
		if( (inicioMateriaAlta < finMateriaHorario && finMateriaHorario <= finMateriaAlta)
			|| (inicioMateriaAlta <= inicioMateriaHorario && inicioMateriaHorario < finMateriaAlta))
		{
			println "Hay un traslape entre dos materias!"
			return true
		}
		else
			return false
			
	}
	
}
